#!/usr/bin/python

import pygame


# These correspond to render queues that are processed in order
RENDER_OBJ_BACKGROUND = 0
RENDER_OBJ_BG_ENTITY= 1
RENDER_OBJ_CHARACTER = 2
RENDER_OBJ_FG_ENTITY= 3
RENDER_OBJ_UI = 4
RENDER_OBJ_MAX = 4 # Make sure this is always the max number above


# Class which handles the simple rendering logic of the game
class RenderEngine:

    # Obvious
    def __init__(self):
        # Init stuff here
        self.m_displayWidth=1024
        self.m_displayHeight=768
        pygame.display.init()
        pygame.display.set_mode((self.m_displayWidth,self.m_displayHeight))
        # Initialize viewport game-world pixel coordinates
        self.m_upperLeftX=0
        self.m_upperLeftY=0
        self.m_upperLeftTargetX=0
        self.m_upperLeftTargetY=0
        self.m_timeLeftToReachTarget=0
        # Setup render queues
        self.m_renderQueue = []
        for i in range(0,RENDER_OBJ_MAX+1):
            self.m_renderQueue.append(set())


    # Obvious
    def cleanup(self):
        # Cleanup
        return None

    # Render this frame.
    def renderFrame(self, elapsedms, absolutems):

        # Update view coordinates if we're moving
        if self.m_timeLeftToReachTarget != 0:
            if elapsedms >= self.m_timeLeftToReachTarget:
                # single step finish
                self.m_upperLeftX=self.m_upperLeftTargetX
                self.m_upperLeftY=self.m_upperLeftTargetY
                self.m_timeLeftToReachTarget=0
            else:
                changeX = ((self.m_upperLeftTargetX - self.m_upperLeftX) * elapsedms) / self.m_timeLeftToReachTarget
                changeY = ((self.m_upperLeftTargetY - self.m_upperLeftY) * elapsedms) / self.m_timeLeftToReachTarget
                self.m_upperLeftX += changeX
                self.m_upperLeftY += changeY
                self.m_timeLeftToReachTarget -= elapsedms

        # Get the surface and lock for drawing
        surface = pygame.display.get_surface()

        # Clear surface to black
        surface.fill((0,0,0))

        # Walk each object batch of objects, drawing
        for queue in self.m_renderQueue:
            for obj in queue:
                obj.draw(surface, self.m_upperLeftX, self.m_upperLeftY)


        # Flip surface to visible
        pygame.display.flip()

    


    # Register a renderable object into a render queue
    def registerObject(self, obj, queue):
        # Add the object to the queue
        self.m_renderQueue[queue].add(obj)
        

    # Unregister a renderable object and remove from render queue
    def unregisterObject(self, obj):
        for queue in self.m_renderQueue:
            if obj in queue:
                queue.remove(obj)

    # Set the upper left coordinates of the viewport in game-world pixel coordinates
    #    Note that the Target coordinates must also be changed or the view will quickly drift back to target   
    def setViewUpperLeft(self, x, y):
        self.m_upperLeftX=x
        self.m_upperLeftY=y
        if self.m_upperLeftX != self.m_upperLeftTargetX or self.m_upperLeftY != self.m_upperLeftTargetY:
            self.m_timeLeftToReachTarget = 500 
        else:
            self.m_timeLeftToReachTarget = 0

    # Set the upper left coordinates of the viewport in game-world pixel coordinates - target
    #  This defines the target coordinates - the renderer will smoothly move the actual coordinates to these
    def setViewTargetUpperLeft(self, x, y, targetTimems = 500):
        # Don't change anything if the values are the same
        if x == self.m_upperLeftTargetX and y == self.m_upperLeftTargetY:
            return
        # Set values
        self.m_upperLeftTargetX=x
        self.m_upperLeftTargetY=y
        # Set time
        if self.m_upperLeftX != self.m_upperLeftTargetX or self.m_upperLeftY != self.m_upperLeftTargetY:
            self.m_timeLeftToReachTarget = targetTimems
        else:
            self.m_timeLeftToReachTarget = 0



    # Retrieve a touple (x,y) of the upper-left coordinates of the viewport in game-world pixel coordinates
    def getViewUpperLeft():
        return (self.m_upperLeftX, self.m_upperLeftY)

    # Retrieve the viewport dimensions
    def getViewDimensions(self):
        return (self.m_displayWidth, self.m_displayHeight)

